﻿<!DOCTYPE html>
<html>
<head>
    <title>JS Exam Exercise 3</title>
    <script>
        function myIndexOf(str, substr, start, end)
        {
            switch(arguments.length)
            {
                case 2:
                    start = 0;
                case 3:
                    end = str.length;
            }
            
            var index = -1;
            for (var idx = start; idx < end; idx++)
            {
                var checkStrIdx = idx;
                index = idx;
                for (var subIdx = 0; subIdx < substr.length; subIdx++)
                {
                    if (str[checkStrIdx] != substr[subIdx])
                    {
                        index = -1;
                        break;
                    }
                    checkStrIdx++;
                }
                if (index >= 0)
                {
                    break;
                }
            }

            return index;
        }
       
        function parseCommandObj(str)
        {
            var varName = "";
            var cmdAction = "";
            var varValuesStr = "";
            var varValues;

            var defIdx = myIndexOf(str, "def");
            var openIdx = myIndexOf(str, "[");
            var closeIdx = myIndexOf(str, "]");

            if (defIdx != -1)
            {
                var varEndIdx = myIndexOf(str, " ", defIdx + 4);
                varName = str.substring(defIdx + 4, varEndIdx);
                cmdAction = str.substring(varEndIdx + 1, openIdx);
            }
            else
            {
                cmdAction = str.substring(0, openIdx);
            }

            varValuesStr = str.substring(openIdx + 1, closeIdx);

            varValuesStr = varValuesStr.replace(/ /g, "");

            varValues = varValuesStr.split(",");

            return {
                varName: varName,
                cmdAction: cmdAction,
                varValues: varValues
            }
        }

        function calculateValue(cmdAction, actionValues)
        {
            var resultValues = [];

            if (cmdAction == "")
            {
                for (var idx = 0; idx < actionValues.length; idx++) {
                    resultValues.push(parseInt(actionValues[idx]));
                }
            }
            else if (cmdAction == "min")
            {
                var minValue = 200001;
                for (var idx = 0; idx < actionValues.length; idx++)
                {
                    var parsedValue = parseInt(actionValues[idx]);
                    if (parsedValue < minValue)
                    {
                        minValue = parsedValue;
                    }
                }
                resultValues.push(minValue);
            }
            else if (cmdAction == "max") {
                var maxValue = -200001;
                for (var idx = 0; idx < actionValues.length; idx++) {
                    var parsedValue = parseInt(actionValues[idx]);
                    if (parsedValue > maxValue) {
                        maxValue = parsedValue;
                    }
                }
                resultValues.push(maxValue);
            }
            else if (cmdAction == "sum") {
                var sumValue = 0;
                for (var idx = 0; idx < actionValues.length; idx++) {
                    sumValue += parseInt(actionValues[idx])
                }
                resultValues.push(sumValue);
            }
            else if (cmdAction == "avg") {
                var avgValue = 0;
                for (var idx = 0; idx < actionValues.length; idx++) {
                    avgValue += parseInt(actionValues[idx])
                }
                if (actionValues.length > 0)
                {
                    avgValue = Math.floor(avgValue / actionValues.length);
                }
                resultValues.push(avgValue);
            }

            return resultValues;
        }

        function Solve(args)
        {
            var resStr = "";
            var commandCount = args.length;
            var variablesStack = {};

            for (var idx = 0; idx < commandCount; idx++)
            {
                var cmdObj = parseCommandObj(args[idx]);
                var cmdValuesLength = cmdObj.varValues.length;
                var resultValues = [];
                // Replace variables with their values
                for (var cmdValuesIdx = 0; cmdValuesIdx < cmdValuesLength; cmdValuesIdx++)
                {
                    var refVar = variablesStack[cmdObj.varValues[cmdValuesIdx]]
                    if (refVar)
                    {
                        for (var newValIdx = 0; newValIdx < refVar.length; newValIdx++)
                        {
                            resultValues.push(refVar[newValIdx]);
                        }
                    }
                    else // if numberic
                    {
                        resultValues.push(cmdObj.varValues[cmdValuesIdx]);
                    }
                }
                cmdObj.varValues = resultValues;
                var cmdValue = calculateValue(cmdObj.cmdAction, cmdObj.varValues);

                if (cmdObj.varName != "")
                {
                    variablesStack[cmdObj.varName] = cmdValue;
                }

                if (idx == commandCount - 1)
                {
                    resStr = cmdValue[0];
                }

            }

            return resStr;
        }

        function execute() {
            // Test 1
            //var args = [];
            //args[0] = "def func sum[5, 3, 7, 2, 6, 3]";
            //args[1] = "def func2 [5, 3, 7, 2, 6, 3]";
            //args[2] = "def func3 min[func2]";
            //args[3] = "def func4 max[5, 3, 7, 2, 6, 3]";
            //args[4] = "def func5 avg[5, 3, 7, 2, 6, 3]";
            //args[5] = "def func6 sum[func2, func3, func4]";
            //args[6] = "sum[func6, func4]";

            // Test 2
            //var args = [];
            //args[0] = "def func sum[1, 2, 3, -6]";
            //args[1] = "def newList [func, 10, 1]";
            //args[2] = "def newFunc sum[func, 100, newList]";
            //args[3] = "[newFunc]";

            // Test 3
            //var args = [];
            //args[0] = "def func sum[1, 2, 3, -6]";
            //args[1] = "sum[func, 4]";
            //args[2] = "def newList [func, 10, 1]";
            //args[3] = "def newFunc sum[func, 100, newList]";
            //args[4] = "[newFunc]";

            // Test 4
            var args = [];
            args[0] = "def func sum[1, 2, 3, -6]";
            args[1] = "def newList [func, 10, 1, func2]";
            args[2] = "def newFunc sum[func, 100, newList]";
            args[3] = "[newFunc]";

            console.log(Solve(args));
        }
    </script>
</head>
<body >
    <button onclick="execute()">execute</button>
</body>
</html>
